package com.qianxun.framework.common.buffer;

import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.BiConsumer;

/**
 * 同步数据缓存池
 * @author: huwei
 * @date: 2019/9/18 15:42
 * @version: 1.0.0
 */
public class SyncDataBuffer {
    private Map<String ,Map<String ,Object>> buffer;

    private Lock lock;

    private SyncDataBuffer(){
        this.buffer = new ConcurrentHashMap<>(16);
        this.lock = new ReentrantLock();
    }

    public static SyncDataBuffer getInstance(){
        return Singleton.instance;
    }

    /**
     * 存入数据
     * @param domain 数据域 ，用于唯一标识同一类的数据 数据域 ，用于唯一标识同一类的数据
     * @param valueKey 数据key 数据key
     * @param value 数据值
     * @return
     */
    public <T> SyncDataBuffer put(String domain , String valueKey , T value){
        lock.lock();
        try {
            Map<String ,Object> map = buffer.get(domain);
            if(map == null) {
                map = new ConcurrentHashMap<>(16);
                buffer.put(domain,map);
            }
            map.put(valueKey ,value);
        }finally {
            lock.unlock();
        }
        return null;
    }

    /**
     * 获取指定域指定值key的值
     * @param domain 数据域 ，用于唯一标识同一类的数据
     * @param valueKey 数据key
     * @return
     */
    public <T> T get(String domain ,String valueKey){
        lock.lock();
        try {
            Map<String ,Object> map = buffer.get(domain);
            if(map != null) {
               return (T) map.get(valueKey);
            }
        }finally {
            lock.unlock();
        }
        return null;
    }

    public int size(String domain){
        Map<String ,Object> map = buffer.get(domain);
        return map == null ? 0 : map.size();
    }

    /**
     * 遍历指定域到数据
     * @param domain 数据域 ，用于唯一标识同一类的数据
     * @param action
     * @return
     */
    public SyncDataBuffer foreach(String domain ,BiConsumer<String ,Object> action){
        lock.lock();
        try {
            Map<String ,Object> map = buffer.get(domain);
            if(map != null) {
                map.forEach(action);
            }
        }finally {
            lock.unlock();
        }
        return this;
    }

    /**
     * 移除指定域中指定值key的值
     * @param domain 数据域 ，用于唯一标识同一类的数据 数据域 ，用于唯一标识同一类的数据
     * @param valueKey 数据key
     * @return
     */
    public SyncDataBuffer remove(String domain ,String valueKey){
        lock.lock();
        try {
            Map<String ,Object> map = buffer.get(domain);
            if(map != null) {
                map.remove(valueKey);
            }
        }finally {
            lock.unlock();
        }
        return this;
    }

    /**
     * 清除指定域
     * @param domain 数据域 ，用于唯一标识同一类的数据 数据域名
     * @return
     */
    public SyncDataBuffer clear(String domain){
        lock.lock();
        try {
            Map<String ,Object> map = buffer.get(domain);
            if(map != null) {
                map.clear();
                buffer.remove(domain);
            }
        }finally {
            lock.unlock();
        }
        return this;
    }

    /**
     * 检索指定域是否存在
     * @param domain 数据域 ，用于唯一标识同一类的数据 域名
     * @return
     */
    public boolean existsDomain(String domain){
        return buffer.containsKey(domain);
    }

    /**
     * 检索指定值key是否存在
     * @param domain 数据域 ，用于唯一标识同一类的数据 域名
     * @param valueKey 数据key 值key
     * @return
     */
    public boolean existsValueKey(String domain ,String valueKey){
        Map<String ,Object> map = buffer.get(domain);
        return map == null ? null : map.containsKey(valueKey);
    }

    /**
     * 创建一个随机域
     * @return
     */
    public String randomDomain(){
        String domain;
        while(buffer.containsKey((domain = UUID.randomUUID().toString()))){}
        return domain;
    }

    private static class Singleton {
        private static SyncDataBuffer instance = new SyncDataBuffer();
    }

}
